home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SPACE 2
/
SPACE - Library 2 - Volume 1.iso
/
utility
/
328
/
v_m_6502.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-10-29
|
24KB
|
778 lines
/***************************************************************************
V_M_6502.C - A virtual machine emulator
(c) 1986 Darek Mihocka
People I'd like to thank before they sue me:
- Ignac Kolenko for helping me code and debug this program.
- Megamax Inc. for making code a joy to write.
- everyone else in Toronto who encouraged me to write this program.
Microprocessor : 6502 @ 250kHz
Hardware : 48K Apple ][
Operating system: none, but one can be loaded from disk
Last update: December 31, 1986
***************************************************************************/
#include <stdio.h>
#include <osbind.h>
#define LOOP while(1)
#define print(x) put_line(x)
#define put(x) outchar(x)
#define CR print("\n\r")
#define BEL '\007'
#define CLS print("\033E")
static char *hex= {"0123456789ABCDEF"} ;
char buf[80] , /* monitor line input buffer */
ch , /* character at buf[tp] */
asc[17] , /* buffer for ASCII dump */
hardcopy, /* if non-zero dumps to printer */
*mem, /* 65536 bytes to simulate 6502 memory */
*stat, /* status bits for each byte */
*scr, /* pointer to start of screen */
*scr_emul ; /* pointer to start of emulation screen */
int len, /* length of inputted line */
tp , /* pointer to current character in buf[] */
MAXCOL ,
MAXROW ,
MAXBYTE ,
hand, /* disk handle */
mode ; /* screen resolution */
int cpu ; /* type of cpu to emulate */
unsigned int pc , /* program counter (16 bits) */
ea ;
unsigned char a,x,y,sp,ir, p, trace ;
struct DTA { /* for disk directories */
char reserved[21] ;
char attrib ;
int time, date ;
long size ;
char fname[11] ;
} ioblock ;
struct disk_info {
long b_free,b_total,b_sec_siz,b_cl_siz ; } diskblock ;
#include "V_M_HDWR.INC"
#include "V_M_OPS.INC"
/*********************************************************************/
help () {
CR ;
print(" *** ST TRANSFORMER DEMO ***\n\r") ;
CR ; CR ;
print(" Syntax: ( all numbers are in hex )\n\r") ;
CR ;
print(" ssss - starting address\n\r") ;
print(" eeee - ending address\n\r") ;
print(" dddd - destination address\n\r") ;
print(" nn - an 8 bit value\n\r") ;
CR ;
print(" Command Summary:\n\r") ;
CR ;
print(" : ssss nn [nn [nn [nn ...]]] - ") ;
print("change contents of memory starting from ssss\n\r") ;
print(" B - ") ;
print("boot up the virtual computer\n\r") ;
print(" D ssss [eeee] - ") ;
print("display memory from ssss to eeee or one line\n\r") ;
print(" G ssss - ") ;
print("start emulating at ssss \n\r") ;
print(" H nn - ") ;
print("nn is non-zero for hardcopy \n\r") ;
print(" I - ") ;
print("index of binary files on the disk\n\r") ;
print(" L ssss [eeee] - ") ;
print("disassemble from ssss to eeee or one page\n\r") ;
print(" M ssss eeee dddd - ") ;
print("move memory block from ssss to dddd\n\r") ;
print(" R file - ") ;
print("read memory block \n\r") ;
print(" S [ssss] - ") ;
print("single step at aaaa or program counter\n\r") ;
print(" T [ssss] - ") ;
print("trace at aaaa or program counter\n\r") ;
print(" V - ") ;
print("view emulated screen display \n\r") ;
print(" W ssss eeee file - ") ;
print("save memory block from ssss to dddd\n\r") ;
print(" X - ") ;
print("exit this great program\n\r") ;
CR ; CR ;
}
outchar(x) char x ; {
Bconout (2,x) ; /* print to screen */
if ((hardcopy)&&(Bconstat(0)))
Bconout (0,x) ; /* print to printer */
}
put_line(lin)
char *lin ; { /* write string to screen */
char c ;
while (c=*lin++) put (c) ;
}
get_line(maxc) int maxc ; { /* get line in buf[], set tp and len */
long key ; /* scan code and character code returned by Bconin */
len = 0 ; /* initialize input line length to 0 */
LOOP {
key = Bconin(2) ; /* get a key */
ch = (char) key ; /* isolate character code */
if (ch>='a' && ch<='z') ch -= 32 ; /* lowercase becomes uppercase */
if (ch>=' ' && ch <='_') { /* if it's printable */
put(ch) ; /* then print it and store it */
buf[len++] = ch ;
} /* if Backspace, delete last */
if (ch==8 && len>0) { /* character and reduce buffer */
print("\b \b") ;
len-- ;
}
if (len==0 && ch==0) { /* if special key */
ch = (char) (key>>16) ; /* get scan code */
if (ch==0x47) CLS ; /* is it Home? */
if (ch==0x62) help() ; /* is it Help? */
break ; /* break out of loop */
}
/* stay in loop until buffer full or Return pressed */
if (len==maxc || ch==13 || ch=='\n' || ch == '\033') break ;
}
CR ;
buf[len] = 0 ; /* terminate input line with a null character */
tp = 0 ; /* text pointer points to first character */
}
skip_space () /* advance tp to point to non-space */
{
while ((ch=buf[tp])==' ' && tp<len) tp++ ;
}
skip_blank () /* advance tp to point to non-blank */
{
while (((ch=buf[tp])<'0' || (ch>'9' && ch<'A') || (ch>'F')) && tp<len) tp++ ;
}
unsigned char get_byte () { /* return 8 bit value at tp */
unsigned char byte=0, digit=0 ;
skip_blank() ;
while ((tp<len) && ( /* find next hex character */
((ch = buf[tp]) >='0' && ch<='9') ||
(ch>='A' && ch<='F')
)
&& (digit++<2) ) {
byte <<= 4 ;
byte += (ch>='0' && ch<='9') ? ch-48 : ch-55 ;
tp++ ;
}
return (byte) ;
}
unsigned int get_addr () { /* return 16 bit value at tp */
unsigned int addr=0, digit=0 ;
skip_blank() ;
while ( (((ch = buf[tp]) >='0' && ch<='9')
|| (ch>='A' && ch<='F'))
&& (digit++<4) ) {
addr <<= 4 ;
addr += (ch>='0' && ch<='9') ? ch-48 : ch-55 ;
tp++ ;
}
return (addr) ;
}
/* disassemble #line commands starting at current pc */
disasm(line) int line ; {
int bits, modes ;
unsigned char opcode ;
long crunch ;
while (line--) {
showpc() ;
opcode = *(mem+pc) ;
crunch = mnemonics[opcode] ;
modes = crunch&0x0FL ;
showhex(pc) ;
put(' ') ;
switch (modes) {
case 0x00 :
case 0x0A : print (" ") ;
break ;
case 0x01 :
case 0x02 :
case 0x03 :
case 0x04 :
case 0x05 :
case 0x06 :
case 0x0B : showhex(pc+1) ;
print (" ") ;
break ;
case 0x07 :
case 0x08 :
case 0x09 :
case 0x0C : showhex(pc+1) ;
put(' ') ;
showhex(pc+2) ;
put(' ') ;
break ;
}
for (bits=24 ; bits >0 ; bits -=8 ) {
put((char)(crunch>>24)) ;
crunch <<= 8 ;
}
put (' ') ;
pc++ ;
switch (modes) {
case 0x00 : print (" ") ;
break ;
case 0x01 : print (" #$") ;
showhex(pc++) ;
print (" ") ;
break ;
case 0x02 : print(" $") ;
showhex(pc++) ;
print (" ") ;
break ;
case 0x03 : print (" $") ;
showhex(pc++) ;
print (",X") ;
print (" ") ;
break ;
case 0x04 : print (" $") ;
showhex (pc++) ;
print (",Y") ;
print (" ") ;
break ;
case 0x05 : print (" ($") ;
showhex (pc++) ;
print (",X)") ;
print (" ") ;
break ;
case 0x06 : print (" ($") ;
showhex (pc++) ;
print ("),Y") ;
print (" ") ;
break ;
case 0x07 : print (" $") ;
showhex (pc+1) ;
showhex (pc) ;
print (" ") ;
pc +=2 ;
break ;
case 0x08 : print (" $") ;
showhex (pc+1) ;
showhex (pc) ;
pc +=2 ;
print (",X") ;
print (" ") ;
break ;
case 0x09 : print (" $") ;
showhex (pc+1) ;
showhex (pc) ;
pc +=2 ;
print (",Y") ;
print (" ") ;
break ;
case 0x0A : print (" A") ;
print (" ") ;
break ;
case 0x0B : print (" $") ;
showaddr (pc + 1 + (int)((char)(*(mem+pc)))) ;
print (" ") ;
pc ++ ;
break ;
case 0x0C : print (" ($") ;
showhex(pc+1) ;
showhex(pc) ;
put (')') ;
print (" ") ;
pc+=2 ;
break ;
default : break ;
}
if (!trace) CR ;
}
}
showreg() {
print ("PC=") ; showpc() ;
print ("A=") ; showbyte(a) ;
print (" X=") ; showbyte(x) ;
print (" Y=") ; showbyte(y) ;
print (" S=") ; showbyte(sp) ;
print (" P=") ; showbyte(p) ;
print (" ") ;
(p&NBIT) ? put('N') : put ('.') ;
(p&VBIT) ? put('V') : put ('.') ;
(p&BBIT) ? put('B') : put ('.') ;
(p&DBIT) ? put('D') : put ('.') ;
(p&IBIT) ? put('I') : put ('.') ;
(p&ZBIT) ? put('Z') : put ('.') ;
(p&CBIT) ? put('C') : put ('.') ;
put (' ') ;
}
/* routine to single step, trace, or execute at current pc */
emulate (count, mode) int count, mode ; {
unsigned int pctemp ;
unsigned char ptemp ;
long usp, start_time, end_time ;
switch (mode) {
case 0 : /* regular emulation */
usp = Super(0L) ; /* must go to supervisor mode */
show_emul() ;
execute() ;
show_scr() ;
Super(usp) ;
showreg() ;
if (trace) print ("EA: ") ;
showaddr (ea) ;
CR ;
trace=0 ;
break ;
case 1 : /* single step mode */
pctemp = pc ; /* remember pc */
disasm(1) ; /* dissassemble current opcode */
pc = pctemp ; /* restore pc */
trace=255 ;
emulate(0,0) ;
break ;
case 2 : /* trace mode */
p &= ~BBIT ;
while (count-- && !(p&BBIT)) emulate(0,1) ;
break ;
}
}
mon() { /* the 6502 monitor */
int quit=0 ; /* quit flag */
char com ; /* command character */
int digit, chptr, cntr ; /* temporary variables */
unsigned addr1, addr2, addr3, byt ;
unsigned char header[6] ;
do {
print ("\n\r>") ; /* print prompt */
get_line(MAXCOL) ; /* get a line of input */
skip_space() ; /* skip any leading spaces */
com = buf[tp++] ; /* get command character */
if (com!='R') addr1 = get_addr() ; /* no numbers for R */
switch(com) {
case '\000' : /* empty line or comment is ignored */
case ';' : break ;
case 'X' : quit++ ; /* X to quit */
break ;
case 'M' : pc = addr1 ; /* block memory move */
addr2 = get_addr() ;
addr3 = get_addr() ;
while (addr1<=addr2) *(mem+addr3++) = *(mem+addr1++) ;
break ;
case ':' : pc = addr1 ; /* modify memory */
skip_blank() ;
while (buf[tp] && (tp<len)) {
*(mem+pc++) = get_byte() ;
skip_blank() ;
}
break ;
case 'D' : pc = addr1 ; /* dump memory */
addr2 = get_addr() ;
if (addr2 <= addr1) addr2 = addr1 + MAXBYTE - 1 ;
do {
showpc() ;
for (cntr=0; cntr<MAXBYTE; cntr++) {
if (pc<=addr2) {
ch = (*(mem+pc))&0x7F ;
asc[cntr] = (ch>=32 && ch<=127) ? ch : '.' ;
showhex(pc++) ;
put (' ');
}
else {
asc[cntr] = ' ' ;
print (" ") ;
}
}
for (cntr=0; cntr<MAXBYTE; cntr++) put(asc[cntr]) ;
CR ;
} while (pc<=addr2 && pc>0x000F) ;
break ;
case 'L' : if (len>1) pc = addr1 ; /* disassemble memory */
disasm(MAXROW-4) ;
break ;
case 'T' : if (len>1) pc = addr1 ; /* trace execution */
p &= ~BBIT ;
emulate(35,2) ;
break ;
case 'B' : pc = (*(mem+0xFFFD)*256)+(*(mem+0xFFFC)) ; /* RESET vector */
p &= ~BBIT ;
emulate(0,0) ;
break ;
case 'G' : pc = addr1 ; /* execute 6502 code */
p &= ~BBIT ;
emulate(0,0) ;
break ;
case 'S' : if (len>1) pc = addr1 ; /* step execution */
(*emulate)(0,1) ;
break ;
case '.' : showreg() ; /* dump registers */
break ;
case 'I' : /* index of binary files, i.e. a directory */
{
int file_count=0 ;
long fre_by ;
Fsetdta(&ioblock) ;
if (Fsfirst("*.BIN",0)>=0) {
print ("Directory of binary files:") ; CR ; CR ;
print ("filename bytes") ; CR ;
do {
file_count++ ;
for (x=0; (x<8) && (ioblock.fname[x] != '.') ;
put(ioblock.fname[x++])) ;
for (;x++<9;put (' ') ) ;
if ((ioblock.size - 6L) < 65537L)
printf ("%6ld\n",ioblock.size-6L);
} while (Fsnext()>=0) ;
}
CR ;
Dfree (&diskblock,0) ;
fre_by = (diskblock.b_sec_siz * diskblock.b_cl_siz *
diskblock.b_free) ;
printf("\n%d file(s) %ld bytes free\n",file_count,fre_by);
fflush (stdout) ;
break ;
}
case 'W' : pc = addr1 ; /* write memory to binary file */
addr2 = get_addr() ;
if (addr2 < addr1) break ;
skip_space() ;
if (tp==len) break ;
strncpy (&buf[len],".bin",5) ; /* append to filename */
if ((hand=Fcreate (&buf[tp],0))<0) break ;
print ("Writing...") ; CR ;
header[0] = header[1] = 255 ;
header[2] = addr1 ; /* lo - hi format */
header[3] = addr1>>8 ;
header[4] = addr2 ;
header[5] = addr2>>8 ;
if (Fwrite (hand,6L,header)<0) {
print ("Write error") ; CR ;
goto err_close ;
}
if (Fwrite
(hand,(long)addr2-(long)addr1+1L,
mem+addr1)<0) {
print ("Write error") ; CR ;
goto err_close ;
}
Fclose (hand) ;
break ;
err_close:
Fclose (hand) ;
break ;
case 'R' : skip_space() ; /* read binary file to memory */
if (tp==len) break ;
strncpy (&buf[len],".bin",5) ;
if ((hand = Fopen (&buf[tp],0))<0) goto err_close ;
print ("Reading... ") ;
if (Fread (hand,6L,header)<0) {
print ("File not found") ; CR ;
goto err_close ;
}
if (header[1]&header[0] != 255) /* verify it's binary file */
{
print ("Not binary file") ;
goto err_close ;
}
addr1 = header[2] + (header[3] << 8) ;
addr2 = header[4] + (header[5] << 8) ;
if (Fread
(hand,(long)addr2-(long)addr1+1L,
mem+addr1)<0) {
print ("EOF reached") ;
goto err_close ;
}
printf ("\nstart %4x end %4x\n",addr1,addr2) ;
Fclose (hand) ;
break ;
case 'H' : hardcopy = addr1 ; /* set hardcopy on/off flag */
break ;
case 'V' : show_emul() ; /* view virtual machine screen */
getchar() ;
show_scr() ;
break ;
default : put(BEL) ; /* otherwise beep */
}
} while (!quit) ;
}
showpc() { /* print out PC */
int bit ;
for (bit = 12; bit>=0; bit-=4) put (hex[(pc>>bit)&0x0F]) ;
print(": ") ;
}
showaddr(addr) unsigned int addr ; /* print 16 bit number */
{
put (hex[addr>>12]) ;
put (hex[(addr>>8)&0x0f]) ;
put (hex[(addr>>4)&0x0f]) ;
put (hex[addr&0x0f]) ;
}
showhex(addr) unsigned int addr ; /* print 8 bit number in memory */
{
unsigned char byte ;
byte = *(mem+addr) ;
put (hex[byte>>4]) ;
put (hex[byte&0x0f]) ;
}
showbyte(byte) unsigned char byte ; /* print 8 bit number */
{
put (hex[byte>>4]) ;
put (hex[byte&0x0f]) ;
}
col25() { /* switch to 25 row color mode */
asm { /* code borrowed from HI50.PRG */
DC.W 0xA000 /* call LINEA to return some pointers */
MOVE.L 4(A1),A1 /* get pointer to 8x8 font data */
MOVE.L 72(A1),-0x0A(A0) /* beats me?? */
MOVE.L 76(A1),-0x16(A0)
MOVE.W #8,-0x2E(A0) /* character height is 8 */
MOVE.W #24,-0x2A(A0) /* 25 rows on the screen */
MOVE.W #1280,-0x28(A0) /* 1280 bytes per screen row */
}
}
mon25() { /* switch to 25 row monochrome mode */
asm {
DC.W 0xA000
MOVE.L 8(A1),A1 /* 8x16 font */
MOVE.L 72(A1),-0x0A(A0)
MOVE.L 76(A1),-0x16(A0)
MOVE.W #16,-0x2E(A0) /* character height is 16 */
MOVE.W #24,-0x2A(A0) /* 25 rows */
MOVE.W #1280,-0x28(A0) /* etc. etc. left to reader */
}
}
mon50() { /* switch to 50 row monochrome mode */
asm {
DC.W 0xA000
MOVE.L 4(A1),A1
MOVE.L 72(A1),-0x0A(A0)
MOVE.L 76(A1),-0x16(A0)
MOVE.W #8,-0x2E(A0)
MOVE.W #43,-0x2A(A0)
MOVE.W #720,-0x28(A0)
}
}
show_emul() { /* display virtual video chip output */
Setscreen (scr_emul,scr_emul,-1) ;
}
show_scr() { /* display 6502 monitor output */
Setscreen (scr,scr,-1) ;
}
colors8() {
if (mode==0) {
Setcolor ( 0,0x0000) ; /* black */
Setcolor ( 3,0x0070) ; /* green */
Setcolor ( 4,0x0070) ;
Setcolor (11,0x0740) ; /* orange */
Setcolor (12,0x0740) ;
Setcolor ( 2,0x0405) ; /* violet */
Setcolor ( 5,0x0405) ;
Setcolor (10,0x0007) ; /* blue */
Setcolor (13,0x0007) ;
Setcolor ( 1,0x0777) ;
Setcolor ( 8,0x0777) ;
Setcolor ( 9,0x0777) ;
Setcolor ( 6,0x0777) ; /* white */
Setcolor ( 7,0x0777) ;
Setcolor (14,0x0777) ;
Setcolor (15,0x0777) ;
}
}
colors16() {
if (mode==0) {
Setcolor ( 0,0x0000) ; /* black */
Setcolor ( 1,0x0500) ; /* magenta */
Setcolor ( 2,0x0004) ; /* dark blue */
Setcolor ( 3,0x0405) ; /* violet */
Setcolor ( 4,0x0030) ; /* dark green */
Setcolor ( 5,0x0444) ; /* grey */
Setcolor ( 6,0x0007) ; /* blue */
Setcolor ( 7,0x0457) ; /* light blue */
Setcolor ( 8,0x0530) ; /* brown */
Setcolor ( 9,0x0740) ; /* orange */
Setcolor (10,0x0222) ; /* grey2 */
Setcolor (11,0x0745) ; /* pink */
Setcolor (12,0x0070) ; /* bright green */
Setcolor (13,0x0770) ; /* yellow */
Setcolor (14,0x0055) ; /* aqua */
Setcolor (15,0x0777) ; /* white */
}
}
/***************************************************************************/
main() {
appl_init() ;
scr = (char *) Physbase() ; /* find screen memory pointer */
scr_emul = scr - 32768L ;
mem = scr - 32768L - 65536L; /* must be on a 64K boundary!!!! */
stat = mem - 65536L + 32768L ; /* use relative addressing */
hardcopy = 0 ; /* hardcopy off */
put(BEL) ; /* beep to announce our arrival */
mode = Getrez() ; /* get current screen resolution */
switch (mode) {
case 0 : col25() ;
MAXCOL = 38 ; /* set variables used by dumping routine */
MAXROW = 24 ;
MAXBYTE = 8 ;
break ;
case 1 : col25() ;
MAXCOL = 78 ;
MAXROW = 24 ;
MAXBYTE = 16 ;
break ;
case 2 : mon50() ;
MAXCOL = 78 ;
MAXROW = 44 ;
MAXBYTE = 16 ;
break ;
}
print ("\033v") ; /* turn text wraparound on just in case */
print ("Atari ST\277 ST Transformer Demo" ) ; CR ;
print ("\275 1986,87 Darek Mihocka") ; CR ;
print ("MegaBaud ST BBS (416)243-9519") ;
CR ;
print ("Applesoft and Integer Basic (c) Apple") ; CR ;
print ("This program is meant to be a demo and") ; CR ;
print ("not to harm Apple in any way.") ; CR ;
CR ;
print ("Release version A2.04 on Dec. 31, 1986") ; CR ;
print ("Microprocessor : 6502 @ 250kHz") ; CR ;
print ("Hardware : 48K Apple ][") ; CR ;
print ("Operating system: none") ; CR ;
CR ;
print ("Coming in mid-1987: The ST Transformer") ; CR ;
print ("Runs Apple, Atari 800, and Commodore 64") ; CR ;
print ("software all on the ST.") ; CR ;
CR ;
InitMachine() ; /* initialize virtual machine memory, pointers, etc. */
mon() ; /* go into monitor */
if (mode == 2) mon25(); /* restore 25 row mode */
else col25() ;
appl_exit() ;
}